#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MAXN=5e4+10;
LL n,m,t2[MAXN*3],v,cnt1,cnt2,yl,yr;
struct tree
{
	LL lc:28,rc:28,sum:36,add:36;
}t1[20000010];
struct oper
{
	LL k,l,r,v;
}op[MAXN];
vector<LL>a;
void push_up(LL o)
{
	t1[o].sum=t1[t1[o].lc].sum+t1[t1[o].rc].sum;
	return;
}
void push_down(LL o,LL l,LL r)
{
	LL mid=(l+r)>>1;
	if(!t1[o].lc)t1[o].lc=++cnt1;
	if(!t1[o].rc)t1[o].rc=++cnt1;
	if(t1[o].add)
	{
		t1[t1[o].lc].add+=t1[o].add;
		t1[t1[o].rc].add+=t1[o].add;
		t1[t1[o].lc].sum+=(mid-l+1)*t1[o].add;
		t1[t1[o].rc].sum+=(r-mid)*t1[o].add;
		t1[o].add=0;
	}
	return;
}
void update1(LL o,LL l,LL r)
{
	if(yl<=l&&r<=yr)
	{
		t1[o].sum+=(r-l+1);
		++t1[o].add;
		return;
	}
	LL mid=(l+r)>>1;
	push_down(o,l,r);
	if(yl<=mid)update1(t1[o].lc,l,mid);
	if(yr>mid)update1(t1[o].rc,mid+1,r);
	push_up(o);
	return;
}
void update2(LL o,LL l,LL r)
{
	LL mid=(l+r)>>1,lc=o<<1,rc=o<<1|1;
	if(!t2[o])t2[o]=++cnt1;
	update1(t2[o],1,n);
	if(l==r)return;
	if(v<=mid)update2(lc,l,mid);
	else update2(rc,mid+1,r);
	return;
}
LL query1(LL o,LL l,LL r)
{
	if(yl<=l&&r<=yr)return t1[o].sum;
	LL mid=(l+r)>>1,ret=0;
	push_down(o,l,r);
	if(yl<=mid)ret=query1(t1[o].lc,l,mid);
	if(yr>mid)ret+=query1(t1[o].rc,mid+1,r);
	return ret;
}
LL query2(LL o,LL l,LL r,LL v)
{
	if(l==r)return l;
	LL mid=(l+r)>>1,lc=o<<1,rc=o<<1|1;
	if(!t2[o])t2[o]=++cnt1;
	LL val=query1(t2[rc],1,n);
	if(val<v)return query2(lc,l,mid,v-val);
	return query2(rc,mid+1,r,v);
}
int main()
{
	scanf("%lld%lld",&n,&m);
	for(LL i=1;i<=m;++i)
	{
		scanf("%lld%lld%lld%lld",&op[i].k,&op[i].l,&op[i].r,&op[i].v);
		if(op[i].k==1)a.push_back(op[i].v);
	}
	sort(a.begin(),a.end());
	a.resize(unique(a.begin(),a.end())-a.begin());
	cnt2=a.size();
	for(LL i=1;i<=m;++i)
	{
		if(op[i].k==1)
		{
			op[i].v=lower_bound(a.begin(),a.end(),op[i].v)-a.begin()+1;
			yl=op[i].l;yr=op[i].r;v=op[i].v;
			update2(1,1,cnt2);
		}
		else
		{
			yl=op[i].l;yr=op[i].r;v=op[i].v;
			printf("%lld\n",a[query2(1,1,cnt2,v)-1]);
		}
	}
	return 0;
}
